package jmetal.qualityIndicator.calculating;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.text.DecimalFormat;
import java.util.StringTokenizer;

import jmetal.core.Problem;
import jmetal.core.Solution;
import jmetal.core.SolutionSet;
import jmetal.qualityIndicator.fastHypervolume.CalculateFastHv;
import jmetal.util.HvIndicator;
import jmetal.util.MathUtil;

public class ComputeHvWFG {

	public static void main(String[] args)
			throws ClassNotFoundException, SecurityException, IOException, NoSuchMethodException,
			InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

		// =====修改此处
		String algName = "NSGAIII";

		String[] probName = { "jmetal.problems.WFG.WFG1", "jmetal.problems.WFG.WFG2", "jmetal.problems.WFG.WFG3",
				"jmetal.problems.WFG.WFG4", "jmetal.problems.WFG.WFG5", "jmetal.problems.WFG.WFG6",
				"jmetal.problems.WFG.WFG7", "jmetal.problems.WFG.WFG8", "jmetal.problems.WFG.WFG9" };

		int[] dimension = { 3, 5, 8, 10 };
		int[] size = {120,210,156,276};
		
		for (int probNum = 0; probNum < 9; probNum++) {
			for (int dimNum = 0; dimNum < dimension.length; dimNum++) {
				Class<?> wfg = Class.forName(probName[probNum]);
				Constructor<?> constr = wfg.getConstructor(String.class, Integer.class, Integer.class, Integer.class);
				Problem problem = (Problem) constr.newInstance("Real", 2 * (dimension[dimNum] - 1), 20,
						dimension[dimNum]);

				String outDirect = "results/" + algName + "/" + problem.getName() + "/"
						+ problem.getNumberOfObjectives() + "D/HV30.dat";
				FileOutputStream output = new FileOutputStream(new File(outDirect));
				System.out.println(outDirect);
				
				double[] hvs = new double[30];
				for (int i = 0; i < 30; i++) {
					String path = "results/" + algName + "/" + problem.getName() +"/"+ problem.getNumberOfObjectives()+"D/FUN"+ i;
					System.out.println(path);

					SolutionSet population = setPopulation(path, size[dimNum]);
					HvIndicator hv = new HvIndicator(problem);
					double hvValue = hv.getHyperVolume(population);
					hvs[i] = hvValue;
					String out = "Run_" + i + ": " + hvValue + "\n";
					output.write(out.getBytes());

					// String outDirect =
					// "results/NSGAIII/"+problem.getName()+"/"+problem.getNumberOfObjectives()+"M_"+i+".log";
					// Logger logger_ = Configuration.logger_;
					// FileHandler fileHandler_ = new FileHandler(outDirect);
					// logger_.addHandler(fileHandler_);
					// logger_.info("Quality indicators");
					// logger_.info("Hypervolume: " +
					// indicators.getHypervolume(population));
					// logger_.info("GD : " + indicators.getGD(population));
					// logger_.info("IGD : " + indicators.getIGD(population));
					// logger_.info("Spread : " +
					// indicators.getSpread(population));
					// logger_.info("Epsilon : " +
					// indicators.getEpsilon(population));
				}
				DecimalFormat aveF= new DecimalFormat("0.0000E00");
				DecimalFormat stdF = new DecimalFormat("0.00E00");
				double ave = MathUtil.getAvarage(hvs);
				double std = MathUtil.getStd(hvs);
				output.write(("ave"+": \t"+aveF.format(ave)+"\n").getBytes());
				output.write(("std"+": \t"+stdF.format(std)+"\n").getBytes());
				output.close();
			}
		}
	}

	private static SolutionSet setPopulation(String path, int size) {

		SolutionSet population = new SolutionSet(size);

		try {
			// Open the file
			FileInputStream fis = new FileInputStream(path);
			InputStreamReader isr = new InputStreamReader(fis);
			BufferedReader br = new BufferedReader(isr);

			int numberOfObjectives = 0;
			String aux = br.readLine();
			int i = 0;
			while (aux != null && i < size) {
				StringTokenizer st = new StringTokenizer(aux);
				int j = 0;
				numberOfObjectives = st.countTokens();
				Solution solution = new Solution(numberOfObjectives);
				while (st.hasMoreTokens()) {
					double value = (new Double(st.nextToken())).doubleValue();
					solution.setObjective(j, value);

					// System.out.println("lambda["+i+","+j+"] = " + value) ;
					j++;
				}
				population.add(i, solution);
				aux = br.readLine();
				i++;
			}
			br.close();
		} catch (Exception e) {
			System.out.println("initUniformWeight: failed when reading for file: " + "/" + path);
			e.printStackTrace();
		}

		return population;
	}

}
